home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Frameworks / Recursive Shell 1.0.1 / Examples / ListFiles ƒ / SearchFolder.c < prev    next >
Text File  |  1996-06-17  |  6KB  |  257 lines

  1. /********************************************************************************/
  2. //
  3. //    Folder Searching Routines
  4. //    
  5. //    Based on code supplied by Andrew Duncan
  6. //
  7. //    Version 1.0.1
  8. //
  9. //    Created:    13 May 1996
  10. //    Modified:    17 June 1996
  11. //
  12. /********************************************************************************/
  13.  
  14. #include    "Main.h"
  15. #include    "DoStuff.h"
  16. #include    "SearchFolder.h"
  17. #include    "DialogUtil.h"
  18. #include    "Utility.h"
  19.  
  20. //    kTimeOut defines how much time (in ticks) the program is willing to wait for
  21. //    other programs to get events while it's stepping though the folders/files.
  22. //    To make the program more multifinder-friendly, make the number bigger.  The
  23. //    downside to this is that the program slows down, especially while in the
  24. //    background.
  25. //    To speed things up, make the number smaller.  This will slow down background
  26. //    applications.  If you go too far, they will become sluggish, and when you
  27. //    switch to, say, the Finder while the program is working, you will become
  28. //    frustrated at how long you have to wait for your clicks to register and
  29. //    whatnot.
  30. #define        kTimeOut    3
  31.  
  32.  
  33. //    Globals
  34.  
  35. static short    sInputVRefNum;
  36.  
  37.  
  38. //    Prototypes
  39.  
  40. Boolean    FSSpecToDirID( FSSpec dirSpec, long* dirID );
  41. static OSErr    ReadDir( long dirID, short dirIndex,
  42.                                                 FSSpec* theSpec, Boolean* isDirectory, long* itsDirID );
  43. Boolean    RecursiveReadDir( long dirID );
  44. Boolean    WorkingEvent( EventRecord        event );
  45. Boolean    WorkingMenu( long menuChoice );
  46.  
  47.  
  48. //
  49. //    DoAllFiles
  50. //
  51. void    DoAllFiles( FSSpec startSpec )
  52. {
  53.     long    dirID;
  54.     
  55.     if ( FSSpecToDirID( startSpec, &dirID ) )
  56.         RecursiveReadDir( dirID );
  57.     else
  58.         DisplayAlert( "\pERROR: Problem processing selected folder name" );
  59. }
  60.  
  61.  
  62. //
  63. //    FSSpecToDirID
  64. //
  65. //    Takes the FSSpec of a directory and returns a DirID to it.
  66. //    Works by creating a FSSpec for a (probably) non-existant file in that
  67. //    directory named "?" and grabbing the ParID field of the new FSSpec.
  68. //    Returns True if successful in getting the directory ID, false otherwise.
  69. //
  70.  
  71. //    Andy sez:
  72. // Should change to just use the ioDrDirID returned by PBGetCatInfo!!!
  73.  
  74. Boolean    FSSpecToDirID( FSSpec dirSpec, long* dirID )
  75. {
  76.     FSSpec    newSpec;
  77.     OSErr    err;
  78.     char    nameLength, i;
  79.  
  80.     sInputVRefNum = dirSpec.vRefNum;
  81.     
  82.     if ( IsAFolder( &dirSpec ) )
  83.     {
  84.         nameLength = dirSpec.name[0];    //    Get the length of directory name
  85.         
  86.         //    Shift the name one character to the right:
  87.         i = nameLength + 1;
  88.         while ( i > 1 )
  89.         {
  90.             dirSpec.name[i] = dirSpec.name[i - 1];
  91.             i--;
  92.         }
  93.         
  94.         dirSpec.name[1] = ':';    //    Make it a partial pathname
  95.         dirSpec.name[nameLength + 2] = ':';    //    Append a colon
  96.         dirSpec.name[nameLength + 3] = '?';    //    An unlikely filename
  97.         dirSpec.name[0] += 3;    //    Fix the length byte for additions
  98.         
  99.         //    Make an FSSpec for the new filename and get the parent ID from it:
  100.         err = FSMakeFSSpec( dirSpec.vRefNum, dirSpec.parID, dirSpec.name, &newSpec );
  101.         
  102.         if ( ( err == noErr ) || ( err == fnfErr ) )
  103.         {
  104.             *dirID = newSpec.parID;
  105.             return ( true );
  106.         }
  107.         else
  108.             return ( false );
  109.     }
  110.     else
  111.         return ( false );
  112. }
  113.  
  114.  
  115. //
  116. //    ReadDir
  117. //
  118. static OSErr    ReadDir( long dirID, short dirIndex,                                                            // Input
  119.                                                 FSSpec* theSpec, Boolean* isDirectory, long* itsDirID )    // Output
  120. {
  121.     CInfoPBRec    pb;
  122.     OSErr                err;
  123.     
  124.     pb.hFileInfo.ioCompletion = (IOCompletionUPP) NULL;
  125.     pb.hFileInfo.ioNamePtr = theSpec->name;
  126.     pb.hFileInfo.ioVRefNum = sInputVRefNum;    //    DANGER!  NEVER SET!
  127.     pb.hFileInfo.ioFDirIndex = dirIndex;        // Find out about nth file
  128.     pb.hFileInfo.ioDirID = dirID;
  129.     
  130.     err = PBGetCatInfo( &pb, false );
  131.     if ( err == noErr )
  132.     {
  133.         err = FSMakeFSSpec(sInputVRefNum, dirID, pb.hFileInfo.ioNamePtr, theSpec);
  134.         *isDirectory = pb.hFileInfo.ioFlAttrib & (1 << 4);
  135.         if (*isDirectory) *itsDirID = pb.dirInfo.ioDrDirID;
  136.         return noErr;
  137.     }
  138.     else
  139.         return err;
  140. }
  141.  
  142.  
  143. //
  144. //    RecursiveReadDir
  145. //    This is the routine which recurses folder to folder, handing off file/folder
  146. //    info to the routines in DoStuff.c
  147. //    The routine returns true when it has finished the folder it is doing normally,
  148. //    false when it is aborted.
  149. //
  150. Boolean    RecursiveReadDir( long dirID )
  151. {
  152.     FSSpec theSpec;
  153.     OSErr err = noErr;
  154.     short dirIndex = 1;    //    What item in the dir to look at - start with 1
  155.     Boolean isDirectory;
  156.     long itsDirID;
  157.     EventRecord        event;
  158.     
  159.     while ( err == noErr )
  160.     {
  161.         BusyCursor();    //    Set the cursor to the watch to show we're doing something.
  162.         
  163.         //    Be a good citizen and let other applications get some processor time,
  164.         //    also check for command-period (abort) at the same time:
  165.         if ( WaitNextEvent( keyDownMask + mDownMask, &event, kTimeOut, nil ) )
  166.         {
  167.             if ( !( WorkingEvent( event ) ) )
  168.                 return( false );
  169.         }
  170.         
  171.         err = ReadDir( dirID, dirIndex, &theSpec, &isDirectory, &itsDirID );
  172.         if ( err == noErr )
  173.         {
  174.             
  175.             if ( isDirectory )
  176.             {
  177.                 if ( !( RecursiveReadDir( itsDirID ) ) )    //    Recurse into the directory
  178.                 {
  179.                     SetCursor(&(qd.arrow));    //    Set the cursor back to the arrow.
  180.                     return ( false );                //    Abort.
  181.                 }
  182.                 DoToEachFolder( theSpec );
  183.             }
  184.             else
  185.                 DoToEachFile( theSpec );
  186.             
  187.             dirIndex++;    //    Move on to the next item
  188.         }
  189.     }
  190.     return ( true );
  191. }
  192.  
  193.  
  194. //
  195. //    WorkingEvent
  196. //    A little mini event handler to detect if the user wants to abort while the
  197. //    program is working.
  198. //
  199. Boolean    WorkingEvent( EventRecord        event )
  200. {
  201.     WindowPtr    window;
  202.     long            menuChoice;
  203.     char            theChar;
  204.     short            thePart;
  205.     
  206.     switch ( event.what )
  207.     {
  208.         case mouseDown:
  209.             thePart = FindWindow( event.where, & window );
  210.             
  211.             switch ( thePart )
  212.             {
  213.                 case inMenuBar:
  214.                     menuChoice = MenuSelect( event.where );
  215.                     if ( !( WorkingMenu( menuChoice ) ) )
  216.                         return ( false );
  217.                     break;
  218.                 case inSysWindow:
  219.                     SystemClick( &event, window );
  220.                     break;
  221.             }
  222.             break;
  223.             
  224.         case keyDown:
  225.         case autoKey:
  226.             if ( event.modifiers & cmdKey )    //    Is the command key pressed?
  227.             {
  228.                 theChar = event.message & charCodeMask;
  229.                 menuChoice = MenuKey( theChar );
  230.                 if ( !( WorkingMenu( menuChoice ) ) )
  231.                     return ( false );
  232.             }
  233.             break;
  234.     }
  235.     return( true );
  236. }
  237.  
  238.  
  239. //
  240. //    WorkingMenu
  241. //    A little mini menu handler to detect if the user wants to abort while the
  242. //    program is working.
  243. //
  244. Boolean    WorkingMenu( long menuChoice )
  245. {
  246.     short    menu, item;
  247.     
  248.     menu = HiWord( menuChoice );
  249.     item = LoWord( menuChoice );
  250.     if ( ( menu == mFile ) && ( item == iOpen ) )    //    The Abort item.
  251.         return( false );
  252.     else
  253.     {
  254.         HandleMenuChoice( menuChoice );    //    Let the main menu procedure deal with it
  255.         return( true );                                    //    Keep on working
  256.     }
  257. }